package com.example.gateway.config;

import cn.dev33.satoken.exception.DisableLoginException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * [Sa-Token 权限认证] 配置类
 *
 * @author lihanbo
 */
@Configuration
public class SaTokenConfigure {

    String[] excludePatterns = new String[]{
            "/**/public/**",
            "/static/**",
            "/doc.html",
            "/swagger-resources/**",
            "/swagger/**",
            "/**/v2/api-docs",
            "/webjars/springfox-swagger-ui/**",
            "/**/v2/api-docs",
            "/**/*.woff2",
            "/**/*.js",
            "/**/*.css",
            "/**/*.jpg",
            "/**/*.png",
            "/**/*.ico"
    };

    // 注册 Sa-Token全局过滤器
    @Bean
    public SaReactorFilter getSaReactorFilter() {
        return new SaReactorFilter()
                // 拦截地址
                .addInclude("/api/**")
                // 开放地址
                .addExclude(excludePatterns)
                // 鉴权方法：每次访问进入
                .setAuth(obj -> {
                    // 权限认证 -- 不同模块, 校验不同权限
//                    SaRouter.match("/api/service01/**", r -> StpUtil.checkPermission("api:service01:*"));
//                    SaRouter.match("/admin/**", r -> StpUtil.checkPermission("admin"));
//                    SaRouter.match("/goods/**", r -> StpUtil.checkPermission("goods"));
//                    SaRouter.match("/orders/**", r -> StpUtil.checkPermission("orders"));
                    // ...
                    // 登录校验 -- 拦截所有路由，并排除/user/doLogin 用于开放登录
                    SaRouter.match("/api/**", r -> StpUtil.checkLogin());
                })
                // 异常处理方法：每次setAuth函数出现异常时进入
                .setError(ex -> {
                    if (ex instanceof NotLoginException) {
                        // 如果是未登录异常
                        NotLoginException ee = (NotLoginException) ex;
                        throw ee;
                    } else if (ex instanceof NotRoleException) {
                        // 如果是角色异常
                        NotRoleException ee = (NotRoleException) ex;
                        throw ee;
                    } else if (ex instanceof NotPermissionException) {
                        // 如果是权限异常
                        NotPermissionException ee = (NotPermissionException) ex;
                        throw ee;
                    } else if (ex instanceof DisableLoginException) {
                        // 如果是被封禁异常
                        DisableLoginException ee = (DisableLoginException) ex;
                        throw ee;
                    }
                    ex.printStackTrace();
                    return SaResult.error(ex.getMessage());
                });
    }
}
